<?php
/*
 * 用于更新表的img字段值
 * 被更新的表必须包含id和img字段，且id为整数自增。
 */

namespace Common\Lib;

class UpdateTableImg
{
    /**
     * @var array 注册表信息 sha1 => id
     */
    private $sha1_list = array();

    /**
     * @var string 当前处理的数据表名称
     */
    private $curr_table = '';

    /**
     * @var array 表对应图片根路径列表
     */
    private $root_list;

    /**
     * UpdateTableImg constructor.
     * @param array $root_list 表名 => 根路径
     */
    public function __construct(array $root_list)
    {
        // 初始化表对应图片根路径列表
        $this->root_list = $root_list;
    }

    /**
     * Main Handler
     */
    public function run()
    {
        $tables = array_keys($this->root_list);
        // 遍历每个数据表
        foreach ($tables as $table) {
            $this->curr_table = $table;
            // 字段为无符号整型，说明表数据已更新过
            if ($this->get_field_type($table) === 'int(10) unsigned') {
                continue;
            }
            $this->update_img($table);
            // 更新表img字段类型为INT
            $this->alter_img_int($table);
        }
    }

    /**
     * 更新表img字段
     * @param $table
     */
    private function update_img($table)
    {
        $model  = M($table);
        $result = $model->getField('id,img');
        if ($result) {
            foreach ($result as $id => $img) {
                if (is_numeric($img)) {
                    continue;
                }
                $file         = $this->get_path($img);
                $info['size'] = $this->get_size($file);
                if ($info['size'] === false) {  // 图片不存在时
                    $model->save(array('id' => $id, 'img' => 0));
                    continue;
                }
                $sha1   = sha1_file($file);
                $img_id = $this->is_reg($sha1);
                if ($img_id === false) {
                    $this->parse_info($img, $info);
                    $info['sha1'] = $sha1;
                    $info['type'] = $this->get_mime_ext($info['ext']);
                    $img_id       = $this->reg($info);
                }
                // 更新数据表记录
                $model->save(array('id' => $id, 'img' => $img_id));
            }
        }
    }

    /**
     * 根据图片扩展名获取MIME类型
     * @param string $ext
     * @return string [未知扩展类型返回空字符串]
     */
    private function get_mime_ext($ext)
    {
        $mime_case = array(
            'bmp'  => 'image/x-ms-bmp',
            'jpg'  => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'gif'  => 'image/gif',
            'png'  => 'image/png',
            'tif'  => 'image/tiff',
            'tiff' => 'image/tiff',
            'tga'  => 'image/x-targa',
            'psd'  => 'image/vnd.adobe.photoshop',
        );
        if (isset($mime_case[$ext])) {
            return $mime_case[$ext];
        } else {
            return '';
        }
    }

    /**
     * 根据表名称及img路径信息获取图片路径
     * 如果为本地路径，返回完整文件名称，七牛云返回url地址
     * @param $img
     * @return string|null $img为空时返回null,否则返回路径字符串
     */
    private function get_path($img)
    {
        if (empty($img)) {
            return null;
        } else {
            if (is_http($img)) {
                return $img;
            } else {
                $root_path = $this->root_list[$this->curr_table];
                return realpath(APP_PATH . '../' . '/' . $root_path . $img);
            }
        }
    }

    /**
     * 解析文件路径信息
     * 解析后包括 dirname basename extension filename 数据项
     * @param string $img
     * @param array  $info
     */
    private function parse_info($img, &$info)
    {
        if (is_http($img)) {
            $info['savetype'] = 'qiniu';
            $path             = ltrim(parse_url(urldecode($img), PHP_URL_PATH), '/');
        } else {
            $info['savetype'] = 'local';
            $path             = $this->root_list[$this->curr_table] . $img;
        }
        $ret              = pathinfo($path);
        $info['name']     = $ret['filename'];
        $info['ext']      = $ret['extension'];
        $info['savename'] = $ret['basename'];
        $info['savepath'] = $ret['dirname'] . '/';
    }

    /**
     * 是否已注册
     * 已注册返回注册的ID，否则返回False
     * @param string $sha1
     * @return int|false
     */
    private function is_reg($sha1)
    {
        if (!isset($this->sha1_list[$sha1])) {
            $id = M('UploadImg')->where(array('sha1' => $sha1))->getField('id');
            if ($id) {
                $this->sha1_list[$sha1] = (int)$id;
            } else {
                return false;
            }
        }
        return $this->sha1_list[$sha1];
    }

    /**
     * 注册图片
     * @param array $info
     * @return int
     */
    private function reg(array $info)
    {
        $ret = M('UploadImg')->data($info)->add();
        return (int)$ret;
    }

    /**
     * 获取文件大小
     * @param string $file 文件的路径或者URL地址
     * @return int|False 如果文件读取失败返回False,否则返回大小
     */
    private function get_size($file)
    {
        $ret = file_get_contents($file);
        if ($ret === false) {
            return false;
        } else {
            return strlen($ret);
        }
    }

    /**
     * 修改表img字段为无符号整型
     * @param string $table
     */
    private function alter_img_int($table)
    {
        // $table = C('DB_PREFIX') . parse_name($table);
        // $sql = 'ALTER TABLE `' . $table . '` MODIFY COLUMN `img` INT UNSIGNED';
        // M()->query($sql);
    }

    /**
     * 获取数据表img字段类型
     * 'int(10) unsigned'表示无符号整数
     * @param string $table
     * @param string $fieldName
     * @return string
     */
    private function get_field_type($table, $fieldName = 'img')
    {
        $table   = C('DB_PREFIX') . parse_name($table);
        $db_name = C('DB_NAME');
        $sql     = "SELECT `column_type` FROM information_schema.columns WHERE table_name='{$table}' AND column_name='{$fieldName}' AND table_schema='{$db_name}'";
        $result  = M()->query($sql);
        $type    = $result[0]['column_type'];
        return $type;
    }
}